import Icon from '@/components/Icon'
import NavBar from '@/components/NavBar'
import { RootState } from '@/store'
import {
  addHistoryAPI,
  clearHistoryAPI,
  clearSuggestionAPI,
  getSuggestionAPI,
} from '@/store/action/search'
import classnames from 'classnames'
import { useEffect, useRef, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import styles from './index.module.scss'
// 引入DOM 净化
import DOMPurify from 'dompurify'
import { Toast } from 'antd-mobile'
import history from '@/utils/history'

export default function Search() {
  // g 表示全部匹配
  // i 表示忽略大小写
  // 🔔知识点：根据传入的变量创建正则对象
  // 利用正则替换高亮字体
  const highlight = (str: string, key: string) => {
    const reg = new RegExp(`(${key})`, 'gi')
    return str.replace(reg, `<span>$1</span>`)
  }

  const dispatch = useDispatch()
  // 受控组件
  const [Keyword, setKeyword] = useState('')

  // 防抖步骤1：准备一个用于存储计时器id的容器
  const timeId = useRef(-1)
  const handleChange = (value: string) => {
    // 更新表单值
    setKeyword(value)
    // 防抖步骤3:清理旧的计时器
    window.clearTimeout(timeId.current)
    // 防抖步骤2: 在用户操作完毕 500 毫秒后, 在发送请求
    timeId.current = window.setTimeout(() => {
      //  如果关键词为空, 不需要发送请求
      if (!value) return
      // 根据关键词展示搜索提示(发送请求)
      dispatch(getSuggestionAPI(value))
    }, 500)
  }

  // 组件卸载时清理定时器
  useEffect(() => {
    return () => {
      window.clearTimeout(timeId.current)
    }
  }, [])

  //   获取仓库数据
  const { suggestion } = useSelector((state: RootState) => state.search)
  const { histories } = useSelector((state: RootState) => state.search)

  //   点击清理搜索
  const handleClear = () => {
    // 清空输入框
    setKeyword('')
    // 清空 Rudex
    dispatch(clearSuggestionAPI())
  }

  //   点击搜索
  const handleSearch = () => {
    //   非空判断
    if (!Keyword) return Toast.show({ content: '请输入内容' })
    // 把关键词添加到历史记录
    dispatch(addHistoryAPI(Keyword))
    // 清空输入框
    setKeyword('')
    // 跳转搜索结果页
    gotoSearchResultPage(Keyword)
  }

  // 去搜索结果页
  const gotoSearchResultPage = (Keyword: string) => {
    // 把关键词添加到历史记录
    dispatch(addHistoryAPI(Keyword))
    // 跳转搜索结果页
    history.push(`/search/result?q=${Keyword}`)
  }

  //   点击清空历史
  const handleClearHistory = () => {
    dispatch(clearHistoryAPI())
  }

  return (
    <div className={styles.root}>
      {/* 顶部导航栏 */}
      <NavBar
        right={
          <span className="search-text" onClick={handleSearch}>
            搜索
          </span>
        }
      >
        <div className="navbar-search">
          <Icon type="iconbtn_search" className="icon-search" />

          <div className="input-wrapper">
            {/* 输入框 */}
            <input
              type="text"
              placeholder="请输入关键字搜索"
              value={Keyword}
              onChange={(e) => handleChange(e.target.value.trim())}
            />

            {/* 清空输入框按钮 */}
            <Icon
              hidden={!Keyword}
              type="iconbtn_tag_close"
              className="icon-close"
              onClick={handleClear}
            />
          </div>
        </div>
      </NavBar>

      {/* 搜索历史 */}
      <div className="history" hidden={!!Keyword}>
        <div className="history-header">
          <span>搜索历史</span>
          <span onClick={handleClearHistory}>
            <Icon type="iconbtn_del" />
            清除全部
          </span>
        </div>

        <div className="history-list">
          {histories.map((item, index) => (
            <span
              onClick={() => gotoSearchResultPage(item)}
              key={index}
              className="history-item"
            >
              {item}
              <span className="divider"></span>
            </span>
          ))}
        </div>
      </div>

      {/* 搜素建议结果列表 */}
      <div hidden={!Keyword} className={classnames('search-result')}>
        {suggestion.map((item, index) => (
          <div
            onClick={() => gotoSearchResultPage(item)}
            key={index}
            className="result-item"
          >
            <Icon className="icon-search" type="iconbtn_search" />
            {/* innerHTML 可写入 <script> 等标签，属于危险操作 */}
            <div
              className="result-value"
              dangerouslySetInnerHTML={{
                //  清理危险代码 DOMPurify
                __html: DOMPurify.sanitize(highlight(item, Keyword)),
              }}
            ></div>
          </div>
        ))}
      </div>
    </div>
  )
}
